(function (global, factory) {
    typeof exports === "object" && typeof module !== "undefined"
        ? (module.exports = factory())
        : typeof define === "function" && define.amd
        ? define(factory)
        : ((global = global || self), (global.tpUtils = factory()));
})(this, function () {
    const isDef = (val) => val !== undefined && val !== null;

    const virtualPathReg = /^(\/[\w, \d, \-, _, \/]+?)\/webroot\//;
    const matchVirtualPathResult = location.pathname.match(virtualPathReg);
    let urlVirtualPath = matchVirtualPathResult ? matchVirtualPathResult[1] : '';
    let virtualPath = urlVirtualPath;

    try {
        virtualPath = tpSaaSCore.getUserInfo().virtualPath || virtualPath
    } catch (e) {}
    const BASE_API = virtualPath + '/api_server';
    const BASE_API2 = '/innovation_screen/api_server';
    const TOKEN_KEY = 'breeding_token';
    Vue.prototype.$axios.defaults.headers['sso-token'] = sessionStorage.getItem(md5(TOKEN_KEY)) || ''

    function request(api, param, method) {
        method = method || "post";
        return new Promise((resolve, reject) => {
            tpHttp[method](
                this,
                api,
                { param: JSON.stringify(param || {}) },
                (data, code, message) => {
                    const res = { data, code, message };
                    if (code == 0) {
                        resolve(data);
                    } else {
                        reject(res);
                    }
                }
            );
        });
    }

    // 接口请求
    function commonRequest(api, param, method) {
        method = method || "post";
        return new Promise((resolve, reject) => {
            tpHttp[method](this, api, param, (data, code, message) => {
                const res = { data, code, message };
                if (code == 0) {
                    resolve(data);
                } else {
                    reject(res);
                }
            });
        });
    }

    let userDetails = {};
    try {
        userDetails = GLOBAL_CONFIG.userDetails();
    } catch (e) {
        userDetails = { unitId: 1911 };
    }

    function rpcIotApi(api_id, key, api_text = `${BASE_API}/fd-system/rpcIotApi`) {
        const param = {
            api_id: api_id,
            key: Object.assign({
                // unitId: userDetails.unitId,
            }, key),
        };
        return request(`${api_text}`, param);
    }

    function parseTime(time, cFormat) {
        if (arguments.length === 0) {
            return null;
        }
        const format = cFormat || "{y}-{m}-{d} {h}:{i}:{s}";
        const date = getDateObj(time);
        const formatObj = {
            y: date.getFullYear(),
            m: date.getMonth() + 1,
            d: date.getDate(),
            h: date.getHours(),
            i: date.getMinutes(),
            s: date.getSeconds(),
            a: date.getDay(),
        };
        const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
            let value = formatObj[key];
            // Note: getDay() returns 0 on Sunday
            if (key === "a") {
                return ["日", "一", "二", "三", "四", "五", "六"][value];
            }
            if (result.length > 0 && value < 10) {
                value = "0" + value;
            }
            return value || 0;
        });
        return timeStr;
    }

    function getDateObj(time) {
        let date;
        if (typeof time === "object") {
            date = time;
        } else {
            if (typeof time === "string") {
                if (/^[0-9]+$/.test(time)) {
                    time = parseInt(time);
                } else {
                    time = time.replace(/\-/g, "/");
                }
            }
            if (typeof time === "number" && time.toString().length === 10) {
                time = time * 1000;
            }
            date = new Date(time);
        }
        return date;
    }

    /**
     * 获取两个日期之间的日期
     * @param start
     * @param end
     * @param type 1：不包含起始日期，包含结束日期 2：包含起始日期，不包含结束日期 3：包含起始日期，包含结束日期
     * @returns {date[]}
     */
    function getBetweenDateStr(start, end, type = 1) {
        const startTime = getDateObj(start);
        const endTime = getDateObj(end);
        const arr = [];
        if (type === 1) {
            while (endTime.getTime() - startTime.getTime() > 0) {
                startTime.setDate(startTime.getDate() + 1);
                arr.push(parseTime(startTime, "{y}-{m}-{d}"));
            }
        } else if (type === 2) {
            while (endTime.getTime() - startTime.getTime() > 0) {
                arr.push(parseTime(startTime, "{y}-{m}-{d}"));
                startTime.setDate(startTime.getDate() + 1);
            }
        } else if (type === 3) {
            while (endTime.getTime() - startTime.getTime() >= 0) {
                arr.push(parseTime(startTime, "{y}-{m}-{d}"));
                startTime.setDate(startTime.getDate() + 1);
            }
        }
        return arr;
    }

    function getBetweenMonthStr(start, end, type = 1) {
        const startTime = getDateObj(start);
        const endTime = getDateObj(end);
        const arr = [];
        if (type === 1) {
            while (endTime.getTime() - startTime.getTime() > 0) {
                startTime.setMonth(startTime.getMonth() + 1);
                arr.push(parseTime(startTime, "{y}-{m}"));
            }
        } else if (type === 2) {
            while (endTime.getTime() - startTime.getTime() > 0) {
                arr.push(parseTime(startTime, "{y}-{m}"));
                startTime.setMonth(startTime.getMonth() + 1);
            }
        } else if (type === 3) {
            while (endTime.getTime() - startTime.getTime() >= 0) {
                arr.push(parseTime(startTime, "{y}-{m}"));
                startTime.setMonth(startTime.getMonth() + 1);
            }
        }
        return arr;
    }

    /**
     * 获得每月的总天数
     * @param {Number} year
     * @param {Number} m
     * @return {Number}
     */
    function daysInMonth(year, month) {
        return /3|5|8|10/.test(month)
            ? 30
            : month === 1
            ? (!(year % 4) && year % 100) || !(year % 400)
                ? 29
                : 28
            : 31;
    }

    /**
     * 比较时间大小
     */
    function dateCompare(startDate, endDate) {
        // 计算截止时间
        startDate = new Date(startDate.replace("-", "/").replace("-", "/"));
        // 计算详细项的截止时间
        endDate = new Date(endDate.replace("-", "/").replace("-", "/"));
        if (startDate <= endDate) {
            return true;
        } else {
            return false;
        }
    }
    function deepMerge(target, merged) {
        for (const key in merged) {
            if (target[key] && typeof target[key] === 'object') {
                deepMerge(target[key], merged[key]);

                continue;
            }

            if (typeof merged[key] === 'object') {
                target[key] = deepClone(merged[key], true);

                continue;
            }

            target[key] = merged[key];
        }

        return target;
    }

    /**
     * 节流原理：在一定时间内，只能触发一次
     *
     * @param {Function} func 要执行的回调函数
     * @param {Number} wait 延时的时间
     * @param {Boolean} immediate 是否立即执行
     * @return null
     */
    function throttle(func, wait = 500, immediate = true) {
        let timer, flag;
        return function() {
            const context = this;
            const args = arguments;

            if (immediate) {
                if (!flag) {
                    flag = true
                    // 如果是立即执行，则在wait毫秒内开始时执行
                    typeof func === 'function' && func.apply(context, args)
                    timer = setTimeout(() => {
                        flag = false
                    }, wait)
                }
            } else if (!flag) {
                flag = true
                // 如果是非立即执行，则在wait毫秒内的结束处执行
                timer = setTimeout(() => {
                    flag = false
                    typeof func === 'function' && func.apply(context, args)
                }, wait)
            }
        }
    }

    /**
     * @desc 函数防抖
     * @param func 函数
     * @param wait 延迟执行毫秒数
     * @param immediate true 表立即执行，false 表非立即执行
     */
    function debounce(func, wait, immediate) {
        let timeout, result;

        const debounced = function () {
            const context = this;
            const args = arguments;

            if (timeout) {
                clearTimeout(timeout);
            }
            if (immediate) {
                // 如果已经执行过，不再执行
                const callNow = !timeout;
                timeout = setTimeout(function () {
                    timeout = null;
                }, wait);
                if (callNow) {
                    result = func.apply(context, args);
                }
            } else {
                timeout = setTimeout(function () {
                    func.apply(context, args);
                }, wait);
            }

            return result;
        };

        debounced.cancel = function () {
            clearTimeout(timeout);
            timeout = null;
        };

        return debounced;
    }

    function deepMerge(target, merged) {
        for (const key in merged) {
            if (target[key] && typeof target[key] === "object") {
                deepMerge(target[key], merged[key]);

                continue;
            }

            if (typeof merged[key] === "object") {
                target[key] = deepClone(merged[key], true);

                continue;
            }

            target[key] = merged[key];
        }

        return target;
    }

    function deepClone(object, recursion = false) {
        if (!object) return object;

        const { parse, stringify } = JSON;

        if (!recursion) return parse(stringify(object));

        const clonedObj = object instanceof Array ? [] : {};

        if (object && typeof object === "object") {
            for (const key in object) {
                if (object.hasOwnProperty(key)) {
                    /* eslint-disable-line */
                    if (object[key] && typeof object[key] === "object") {
                        clonedObj[key] = deepClone(object[key], true);
                    } else {
                        clonedObj[key] = object[key];
                    }
                }
            }
        }

        return clonedObj;
    }

    // 判断是否为空
    function validatenull(val) {
        if (typeof val === "boolean") {
            return false;
        }
        if (val instanceof Array) {
            if (val.length === 0) return true;
        } else if (val instanceof Object) {
            if (JSON.stringify(val) === "{}") return true;
        } else {
            if (
                val === "null" ||
                val == null ||
                val === "undefined" ||
                val === undefined ||
                val === ""
            )
                return true;
            return false;
        }
        return false;
    }

    // 数字
    function isNumber(value) {
        if (isNaN(value)) {
            return false;
        }
        return typeof +value === "number";
    }

    function toNumber(value, fractionDigits = 2) {
        return isNumber(value) ? Number(value).toFixed(fractionDigits) - 0 : 0;
    }

    function observerDomResize(dom, callback) {
        const MutationObserver =
            window.MutationObserver ||
            window.WebKitMutationObserver ||
            window.MozMutationObserver;

        const observer = new MutationObserver(callback);

        observer.observe(dom, {
            attributes: true,
            attributeFilter: ["style"],
            attributeOldValue: true,
        });

        return observer;
    }

    function formatNumber(number) {
        var arr = (number + "").split(".");
        var int = arr[0].split("");
        var fraction = arr[1] || "";
        var r = "";
        var len = int.length;
        int.reverse().forEach(function (v, i) {
            if (i !== 0 && i % 3 === 0) {
                r = v + "," + r;
            } else {
                r = v + r;
            }
        });
        return r + (!!fraction ? "." + fraction : "");
    }

    function pieChartAnimation(chart, data, seriesIndex) {
        if (data.length <= 1) return;
        seriesIndex = seriesIndex || 0;
        let index = 0;
        let timer = null;

        function highlightChange(index) {
            for (let i = 0; i < data.length; i++) {
                if (index === i) {
                    chart.dispatchAction({
                        type: "highlight",
                        seriesIndex: seriesIndex,
                        dataIndex: i,
                    });
                } else {
                    chart.dispatchAction({
                        type: "downplay",
                        seriesIndex: seriesIndex,
                        dataIndex: i,
                    });
                }
            }
        }

        function startAnimation() {
            stopAnimation();
            timer = setInterval(() => {
                index++;
                if (index === data.length) {
                    index = 0;
                }
                highlightChange(index);
            }, 2000);
        }

        function stopAnimation() {
            clearInterval(timer);
        }

        highlightChange(0);
        startAnimation();
        chart.on("mouseover", (e) => {
            index = e.dataIndex;
            stopAnimation();
            highlightChange(index);
        });
        chart.on("mouseout", (e) => {
            index = e.dataIndex;
            startAnimation();
            // highlightChange(index);
        });
        chart.stopAnimation = stopAnimation;
    }

    function pieChartAnimation2(chart, option, data, callback) {
        if (data.length <= 1) return;
        let index = 0;
        let timer = null;
        function highlightChange(index) {
            option.series[0].data = data;
            option.plotOptions.pie.events = {
                click(e) {
                    index = e.point.index;
                },
                mouseOver(e) {
                    // index = e.target.index;
                    stopAnimation();
                    // highlightChange(index);
                },
                mouseOut(e) {
                    startAnimation();
                },
            };
            chart.update(option);
            for (let i = 0; i < data.length; i++) {
                const active = index === i;
                const item = data[i];
                data[i].sliced = active;
                data[i].selected = active;
                if (active) {
                    callback && callback(item);
                }
            }
        }

        function startAnimation() {
            stopAnimation();
            timer = setInterval(() => {
                index++;
                if (index === data.length) {
                    index = 0;
                }
                highlightChange(index);
            }, 2000);
        }

        function stopAnimation() {
            clearInterval(timer);
        }

        highlightChange(0);
        startAnimation();
        chart.stopAnimation = stopAnimation;
    }

    function getMatchRegionValue(regionCode) {
        regionCode = (regionCode || "").toString();
        const matchArr = regionCode.match(/0+$/);
        let len = 0;
        let value = "";
        if (matchArr) {
            len = matchArr[0].length;
            len = len % 2 === 0 ? len : len - 1; // 必须为偶数
            len = len > 0 ? len : 0;
        }
        if (len) {
            value = regionCode.slice(0, -len);
        } else {
            value = regionCode;
        }
        return value;
    }

    // 换算方法
    function getResizePx(px, defaultWidth = 1920) {
        const width = document.documentElement.clientWidth;
        return px * (width / defaultWidth);
    }

    function getVerticalResizePx(px, defaultWidth = 1080) {
        const width = document.documentElement.clientHeight;
        return px * (width / defaultWidth);
    }

    function getDataMapping(data, key) {
        return data.reduce((pre, cur) => {
            if (pre[cur[key]]) {
                pre[cur[key]].push(cur);
            } else {
                pre[cur[key]] = [cur];
            }
            return pre;
        }, {});
    }

    function getRandomArbitrary(min, max) {
        return Math.random() * (max - min) + min;
    }

    function getRandomInt(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min)) + min; // 不含最大值，含最小值
    }

    function getRandomIntInclusive(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min; // 含最大值，含最小值
    }

    function getRandomColor(min = 0, max = 255) {
        return `rgb(${getRandomIntInclusive(
            min,
            max
        )}, ${getRandomIntInclusive(min, max)}, ${getRandomIntInclusive(min, max)})`;
    }

    // 获取图形中心坐标
    function calculateCenter(lnglatarr) {
        var total = lnglatarr.length;
        var X = 0;
        var Y = 0;
        var Z = 0;

        lnglatarr
            .map((arr) => ({ lng: arr[0], lat: arr[1] }))
            .forEach(function (lnglat) {
                var lng = (lnglat.lng * Math.PI) / 180;
                var lat = (lnglat.lat * Math.PI) / 180;
                var x, y, z;
                x = Math.cos(lat) * Math.cos(lng);
                y = Math.cos(lat) * Math.sin(lng);
                z = Math.sin(lat);
                X += x;
                Y += y;
                Z += z;
            });

        X = X / total;
        Y = Y / total;
        Z = Z / total;

        var Lng = Math.atan2(Y, X);
        var Hyp = Math.sqrt(X * X + Y * Y);
        var Lat = Math.atan2(Z, Hyp);

        // return new AMap.LngLat(Lng * 180 / Math.PI, Lat * 180 / Math.PI);
        return [(Lng * 180) / Math.PI, (Lat * 180) / Math.PI];
    }

    /**
     * 十六进制颜色转换为带透明度的颜色
     * @param _color 十六进制颜色
     * @param _opactity 透明度
     * @returns {string} rgba
     */
    function hexToRGBA(_color, _opacity) {
        let sColor = _color.toLowerCase();
        // 十六进制颜色值的正则表达式
        const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
        // 如果是16进制颜色
        if (sColor && reg.test(sColor)) {
            if (sColor.length === 4) {
                let sColorNew = "#";
                for (let i = 1; i < 4; i += 1) {
                    sColorNew += sColor
                        .slice(i, i + 1)
                        .concat(sColor.slice(i, i + 1));
                }
                sColor = sColorNew;
            }
            // 处理六位的颜色值
            const sColorChange = [];
            for (let i = 1; i < 7; i += 2) {
                sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));
            }
            return "rgba(" + sColorChange.join(",") + "," + _opacity + ")";
        }
        return sColor;
    }

    function getNavData({ items = [], activeCode = "", activeChildCode = "" }) {
        const navList = [];
        let childNavList = [];
        items.forEach((item) => {
            if (item.code == activeCode) {
                item.active = true;
                childNavList = item.children || [];
            }
            const children = item.children;
            let href = item.href || "javascript:;";
            let target = item.target || "_self";
            if (Array.isArray(children) && children.length) {
                let matchChild = null;
                children.forEach((child) => {
                    child.href = this.$aHrefHandle(child.href || "", {
                        code: item.code,
                        childCode: child.code,
                    });
                    if (child.code == activeChildCode) {
                        matchChild = child;
                        // child.active = true;
                    }
                });
                if (!matchChild) {
                    matchChild = children[0];
                }
                matchChild.active = true;
                if (item.code != activeCode) {
                    href = this.$aHrefHandle(matchChild.href || "", {
                        code: item.code,
                        childCode: matchChild.code,
                    });
                    target = matchChild.target;
                }
            } else {
                if (item.code != activeCode) {
                    href = this.$aHrefHandle(item.href || "", {
                        code: item.code,
                    });
                    target = item.target;
                }
            }
            navList.push(Object.assign({}, item, { href, target }));
        });
        return {
            navList,
            childNavList,
        };
    }

    /**
     * 求百分比
     * @param  num 当前数
     * @param  total 总数
     */
    function getPercent(num, total) {
        num = parseFloat(num);
        total = parseFloat(total);
        if (isNaN(num) || isNaN(total)) {
            return 0;
        }
        return total <= 0 ? 0 : Math.round((num / total) * 10000) / 100.0;
    }

    // 可以将数字转换成中文大写的表示，处理到万级别，例如 toChineseNum(12345)，返回 一万二千三百四十五
    function toChineseNum(num) {
        const changeNum = [
            "零",
            "一",
            "二",
            "三",
            "四",
            "五",
            "六",
            "七",
            "八",
            "九",
        ]; // changeNum[0] = "零"
        const unit = ["", "十", "百", "千", "万"];
        num = parseInt(num);
        const getWan = (temp) => {
            const strArr = temp.toString().split("").reverse();
            let newNum = "";
            for (let i = 0; i < strArr.length; i++) {
                newNum =
                    (i == 0 && strArr[i] == 0
                        ? ""
                        : i > 0 && strArr[i] == 0 && strArr[i - 1] == 0
                        ? ""
                        : changeNum[strArr[i]] +
                          (strArr[i] == 0 ? unit[0] : unit[i])) + newNum; // eslint-disable-line
            }
            return newNum;
        };
        const overWan = Math.floor(num / 10000);
        let noWan = num % 10000;
        if (noWan.toString().length < 4) noWan = "0" + noWan;
        return overWan ? getWan(overWan) + "万" + getWan(noWan) : getWan(num);
    }

    // 获取风向
    function windDirection(dtn) {
        let direction = "";
        if ((dtn >= 337.6 && dtn <= 360) || (dtn >= 0 && dtn <= 22.5)) {
            direction = "北风";
        } else if (dtn >= 22.6 && dtn <= 67.5) {
            direction = "东北风";
        } else if (dtn >= 67.6 && dtn <= 112.5) {
            direction = "东风";
        } else if (dtn >= 112.6 && dtn <= 157.5) {
            direction = "东南风";
        } else if (dtn >= 157.6 && dtn <= 202.5) {
            direction = "南风";
        } else if (dtn >= 202.6 && dtn <= 247.5) {
            direction = "西南风";
        } else if (dtn >= 247.6 && dtn <= 292.5) {
            direction = "西风";
        } else if (dtn >= 292.6 && dtn <= 337.5) {
            direction = "西北风";
        }
        return direction;
    }
    //换算方法
    function nowSize(val, initWidth = 1920) {
        let nowClientWidth = document.documentElement.clientWidth;
        return val * (nowClientWidth / initWidth);
    }

    const cubic = (value) => Math.pow(value, 3);
    const easeInOutCubic = (value) =>
        value < 0.5 ? cubic(value * 2) / 2 : 1 - cubic((1 - value) * 2) / 2;
    const scrollToTop = (el) => {
        const beginTime = Date.now();
        const beginValue = el.scrollTop;
        const rAF =
            window.requestAnimationFrame || ((func) => setTimeout(func, 16));
        const frameFunc = () => {
            const progress = (Date.now() - beginTime) / 500;
            if (progress < 1) {
                el.scrollTop = beginValue * (1 - easeInOutCubic(progress));
                rAF(frameFunc);
            } else {
                el.scrollTop = 0;
            }
        };
        rAF(frameFunc);
    };

    function getYearOnYear(preVal, curVal) {
        let yearOnYear = '';
        if (tpUtils.toNumber(curVal, 10) && tpUtils.toNumber(preVal, 10)) {
            yearOnYear = ((curVal - preVal) / Math.abs(preVal) * 100);
        }
        return tpUtils.toNumber(yearOnYear);
    }

    function getFormatterText(text, number, separator) {
        number = number || 3;
        separator = separator || '\n'; // 或 <br>
        var newParamsName = ''; // 返回文字格式
        var paramsNameNumber = text.length; // 获取显示文字长度
        var rowNumber = Math.ceil(paramsNameNumber / number); // 最多能显示几行
        if (paramsNameNumber > number) {
            // 如果长度大于每行最多显示的字数
            for (var p = 0; p < rowNumber; p++) {
                // 循环次数就是行数
                var tempStr = ''; // 每次截取的字符
                var start = p * number; // 截取的起点
                var end = start + number; // 截取的终点
                if (p == rowNumber - 1) {
                    // 最后一行就不换行了
                    tempStr = text.substring(start);
                } else {
                    tempStr = text.substring(start, end) + separator;
                }
                newParamsName += tempStr; // 拼接字符串
            }
        } else {
            newParamsName = text; // 如果小于每行最多显示的字数就返回原来的字符串
        }
        return newParamsName;
    }
    //传入数组以及分组的属性
    function groupBy(objArray,property){
        return objArray.reduce(function(acc,obj){
            let key = obj[property];
            if(!acc[key]){
                acc[key] = []
            }
            acc[key].push(obj);
            return acc;
        },{})
    }
    // 求出总的占比
    function getPercentValue(arrList, index, precision) {
        if (!arrList[index]) {
            return 0;
        }
        if (!precision) precision = 2;
        let sum = arrList.reduce((acc, val) => {
            return acc + (isNaN(val) ? 0 : val);
        }, 0);
        if (sum === 0) {
            return 0;
        }
        let digits = Math.pow(10, precision);
        let votesPerQuota = arrList.map((val) => {
            return (isNaN(val) ? 0 : val) / sum * digits * 100;
        });
    
        let targetSeats = digits * 100;
        let seats = votesPerQuota.map((votes) => {
            return Math.floor(votes);
        });
    
        let currentSum = seats.reduce((acc, val) => {
            return acc + val;
        }, 0);
     
        let remainder = votesPerQuota.map(function (votes, index) {
            return votes - seats[index];
        });
       
        while (currentSum < targetSeats) {
            let max = Number.NEGATIVE_INFINITY;
            let maxId = null;
            for (let i = 0, len = remainder.length; i < len; ++i) {
                if (remainder[i] > max) {
                    max = remainder[i];
                    maxId = i;
                }
            }
            ++seats[maxId];
            remainder[maxId] = 0;
            ++currentSum;
        }
    
        return seats[index] / digits;
    }
    // 加密对象
    function encodeObj(obj) {
        return btoa(encodeURIComponent(JSON.stringify(obj)));
    }
    /* 
    获取饼图百分比
    */
    function getPercentageValue(value, total, fractionDigits = 2) {
        if (value == 0 || !value) return 0;
        let percentage = tpUtils.toNumber(value / total * 100, fractionDigits);
        if (fractionDigits == 0) {
            percentage = percentage == 0 ? '< 1' : percentage;
        } else {
            percentage = percentage == 0 ? '< ' + '0.' + '1'.padStart(fractionDigits, '0') : percentage;
        }
        return percentage;
    }

    function addTabHandle({
      name,
      label,
      url,
      height,
      showSubmitBtn = false,
      activeTabRefresh = true,
    }) {
      let layout_type = MACRO_VARIABLE.CURRENTURL_PARAM("layout_type") || "";
      let thiz =
        (window.top != window.self && layout_type ? top.vm : this) || this;
      let opt = {
        name,
        label,
        url,
        closable: true,
        height,
        showSubmitBtn,
        activeTabRefresh,
      };
      console.log(thiz.$refs["app"])
      console.log(thiz.$refs["app"].$refs["tabs2"])
      thiz.$refs["app"].$refs["tabs2"].addIframeSingleTab(opt, true);
    }
    function closeCurrentTabHandle() {
      try {
        const parentWindowAppVue =
          parent.window.document.getElementById("app").__vue__.$root;
        const tabController = parentWindowAppVue.$refs["app"].$refs["tabs2"];
        tabController.removeTab(tabController.activeName);
      } catch (error) {
        console.error(`tab标签页关闭失败:${error}`);
      }
    }

    return {
        isDef,
        request,
        commonRequest,
        parseTime,
        getBetweenDateStr,
        getBetweenMonthStr,
        daysInMonth,
        dateCompare,
        debounce,
        deepMerge,
        deepClone,
        validatenull,
        isNumber,
        toNumber,
        formatNumber,
        observerDomResize,
        pieChartAnimation,
        pieChartAnimation2,
        getMatchRegionValue,
        getResizePx,
        getVerticalResizePx,
        getDataMapping,
        getRandomArbitrary,
        getRandomInt,
        getRandomIntInclusive,
        getRandomColor,
        calculateCenter,
        hexToRGBA,
        getNavData,
        getPercent,
        toChineseNum,
        windDirection,
        nowSize,
        scrollToTop,
        getYearOnYear,
        getFormatterText,
        groupBy,
        BASE_API,
        BASE_API2,
        userDetails,
        getPercentValue,
        rpcIotApi,
        encodeObj,
        
        throttle,
        getPercentageValue,

        addTabHandle,
        closeCurrentTabHandle
    };
});
